//
//  TXLiteManager.swift
//  onemeetingmac
//
//  Created by 张衡 on 2019/12/20.
//  Copyright © 2019 onemeeting. All rights reserved.
//

import Foundation

class TParams: TRTCParams {
    
}

class TXLiteManager: NSObject {
    
    private override init() {} // 私有化init方法
    private static var _shared:TXLiteManager?
    class func shared() -> TXLiteManager {
        guard let instance = _shared else {
            self._shared = TXLiteManager()
            return _shared!
        }
        return instance
    }
    
    class func destroy() {
        self.isEntered = false
        self._shared = nil
    }
    
    var isLiving:Bool            = false
    var pushType:OnePushType {
        return Td.sh().cloud.hasLive ? .live:.record
    }
    
    /*
    是否已经进入会议了
    */
    static var isEntered:Bool = false
    
    var ksta:[TkStatistics] = []
    
    var delegate:TRTCCloudDelegate? {
        didSet {
            TRTCCloud.sharedInstance()?.delegate = delegate
        }
    }
    
    func sdkAuto() {
        self.rtcDefult()
    }
    
    func setBeauty(isOn:Bool) {
        let beautyManger = TRTCCloud.sharedInstance()?.getBeautyManager()
        if isOn {
            beautyManger?.setBeautyStyle(TXBeautyStyle.smooth)
            beautyManger?.setBeautyLevel(3)
            beautyManger?.setWhitenessLevel(8)
            beautyManger?.setRuddyLevel(8)
        }else {
            beautyManger?.setBeautyStyle(TXBeautyStyle.nature)
            beautyManger?.setBeautyLevel(0)
            beautyManger?.setWhitenessLevel(0)
            beautyManger?.setRuddyLevel(0)
        }
        
    }
    
    func rtcDefult()  {
        self.setBeauty(isOn: true)
        TRTCCloud.sharedInstance()?.enableAudioVolumeEvaluation(300)
    }
    
    func switchRole(_ type:TRTCRoleType)  {
        TRTCCloud.sharedInstance()?.switch(type)
    }
    
    func setRemoteViewFillMode(userId:String,mode:TRTCVideoFillMode) {
        TRTCCloud.sharedInstance()?.setRemoteViewFillMode(userId, mode: mode)
    }
    
    func setLocalViewFillMode(mode:TRTCVideoFillMode) {
        TRTCCloud.sharedInstance()?.setLocalViewFillMode(mode)
    }
    
    /// 扬声器设备列表，第一项为当前系统默认设备
    func getSpeakerDevicesList() -> [TRTCMediaDeviceInfo]? {
        return TRTCCloud.sharedInstance().getSpeakerDevicesList()
    }
    
    /// 设置要使用的扬声器
    /// - Parameter deviceId: 设备id
    @discardableResult
    func setCurrentSpeakerDevice(deviceId:String) -> Int {
        return Int((TRTCCloud.sharedInstance().setCurrentSpeakerDevice(deviceId)))
    }
    
    /// 当前扬声器设备信息
    func getCurrentSpeakerDevice() -> TRTCMediaDeviceInfo? {
        return TRTCCloud.sharedInstance().getCurrentSpeakerDevice()
    }
    
    func getMicDevicesList() -> [TRTCMediaDeviceInfo]? {
        return TRTCCloud.sharedInstance().getMicDevicesList()
    }
    
    func getCurrentMicDevice() -> TRTCMediaDeviceInfo? {
        return TRTCCloud.sharedInstance().getCurrentMicDevice()
    }
    
    @discardableResult
    func setCurrentMicDevice(deviceId:String) -> Int {
        return Int((TRTCCloud.sharedInstance().setCurrentMicDevice(deviceId)))
    }
    
    func getCameraDevicesList() -> [TRTCMediaDeviceInfo]? {
        return TRTCCloud.sharedInstance().getCameraDevicesList()
    }
    
    func getCurrentCameraDevice() -> TRTCMediaDeviceInfo? {
        return TRTCCloud.sharedInstance().getCurrentCameraDevice()
    }
    
    @discardableResult
    func setCurrentCameraDevice(deviceId:String) -> Int {
        return Int((TRTCCloud.sharedInstance().setCurrentCameraDevice(deviceId)))
    }
    
    //本地音频静音和解除
    func muteLocalAudio(_ isok:Bool) {
        TRTCCloud.sharedInstance().muteLocalAudio(isok)
    }
    
    //关闭本地音频
    func stopLocalAudio() {
        TRTCCloud.sharedInstance().stopLocalAudio()
    }
    
    //开启本地音频
    func startLocalAudio() {
        TRTCCloud.sharedInstance().startLocalAudio()
    }
    
    /// 全部远程视频静音
    /// - Parameter isok: ture静音，false解除静音
    func muteAllRemoteAudio(_ isok:Bool) {
        TRTCCloud.sharedInstance().muteLocalAudio(isok)
    }
    
    //本地视频屏蔽和解除
    func muteLocalVideo(_ isok:Bool) {
        TRTCCloud.sharedInstance().muteLocalVideo(isok)
    }
    
    /// 本地视频
    /// - Parameter view: 容器
    func startLocalPreview(view:NSView) {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
            TRTCCloud.sharedInstance().startLocalPreview(view)
            TRTCCloud.sharedInstance().setLocalViewFillMode(TRTCVideoFillMode.fit)
            TRTCCloud.sharedInstance()?.setLocalViewMirror(false)
        }
    }
    
    func stopLocalPreview()  {
        TRTCCloud.sharedInstance().stopLocalPreview()
    }
    
    /// 远程视频
    /// - Parameters:
    ///   - userId: id
    ///   - view: 容器
    func startRemoteView(userId:String,view:NSView) {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
            TRTCCloud.sharedInstance().startRemoteView(userId, view: view)
            TRTCCloud.sharedInstance()?.setRemoteViewFillMode(userId, mode: TRTCVideoFillMode.fit)
        }
    }
    
    func stopRemoteView(userId:String)  {
        TRTCCloud.sharedInstance().stopRemoteView(userId)
    }
    
    func stopAllRemoteView()  {
        TRTCCloud.sharedInstance()?.stopAllRemoteView()
    }
    
    /// 接收到共享流开启
    /// - Parameter userId: String id
    /// - Parameter view: NSView 容器
    func startRemoteSubStreamView(userId:String,view:NSView) {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
            TRTCCloud.sharedInstance()?.startRemoteSubStreamView(userId, view: view)
        }
    }
    
    /// 接收到共享流关闭
    /// - Parameter userId: String id
    func stopRemoteSubStreamView(userId:String) {
        TRTCCloud.sharedInstance()?.stopRemoteSubStreamView(userId)
    }
    
    /// 进入视频房间
    /// - Parameter param: TRTCParams 参数
    /// - Parameter scene: TRTCAppScene 直播和普通模式
    func enterRoom(param:TRTCParams,scene:TRTCAppScene) -> () {
        TRTCCloud.sharedInstance().enterRoom(param, appScene: scene)
    }
    /// 结束房间
    func exitRoom() {
        TRTCCloud.sharedInstance()?.stopLocalPreview()
        TRTCCloud.sharedInstance()?.stopAllRemoteView()
        TRTCCloud.sharedInstance().exitRoom()
    }
    
    /// 发送自定义消息给房间内所有用户
    /// - Parameters:
    ///   - cmdID: 消息 ID，取值范围为1 - 10
    ///   - data: 待发送的消息，最大支持1KB（1000字节）的数据大小
    ///   - reliable: 是否可靠发送，可靠发送的代价是会引入一定的延时，因为接收端要暂存一段时间的数据来等待重传
    ///   - ordered: 是否要求有序，即是否要求接收端接收的数据顺序和发送端发送的顺序一致，这会带来一定的接收延时，因为在接收端需要暂存并排序这些消息。
    @discardableResult
    func sendCustomCmdMsg(_ cmdID:Int,data:Data,reliable:Bool,ordered:Bool) -> Bool? {
        return TRTCCloud.sharedInstance().sendCustomCmdMsg(cmdID, data: data, reliable: reliable, ordered: ordered)
    }
    
    //MARK:- 共享
    
    /// 枚举可分享的屏幕窗口
    /// 如果您要给您的 App 增加屏幕分享功能，一般需要先显示一个窗口选择界面，这样用户可以选择希望分享的窗口。
    /// 通过下列函数，您可以获得可分享窗口的 ID、类型、窗口名称以及缩略图。
    /// 获取上述信息后，您就可以实现一个窗口选择界面。您也可以使用 Demo 源码中已经实现好的窗口选择界面。
    /// - Parameters:
    ///   - withThumbnailSize: 指定要获取的窗口缩略图大小，缩略图可用于绘制在窗口选择界面上
    ///   - iconSize: 指定要获取的窗口图标大小
    func getScreenCaptureSources(with thumbnailSize:CGSize,iconSize:CGSize) -> [TRTCScreenCaptureSourceInfo]?  {
        return TRTCCloud.sharedInstance().getScreenCaptureSources(withThumbnailSize:thumbnailSize, iconSize: iconSize)
    }
    
    /// 开启共享
    /// - Parameter view: 容器
    func startScreenCapture(_ view:NSView?,param:VideoEncoderShareParam)  {
        let videoparam = TRTCVideoEncParam()
        videoparam.enableAdjustRes = param.enableAdjustRes
        videoparam.videoResolution = TXLiteManager._resolutionFrom(string: param.videoResolution)
        videoparam.resMode = TRTCVideoResolutionMode.init(rawValue: param.resMode) ?? TRTCVideoResolutionMode.landscape
        videoparam.videoBitrate = Int32(param.videoBitrate)
        videoparam.videoFps = Int32(param.videoFps)
        TRTCCloud.sharedInstance()?.startScreenCapture(view, streamType: TRTCVideoStreamType.sub, encParam: videoparam)
    }
    
    /// 停止共享
    @discardableResult
    func stopScreenCapture() -> Bool {
        let isok = TRTCCloud.sharedInstance().stopScreenCapture()==0 ? true:false
        return isok
    }
    
    /// 暂停共享
    @discardableResult
    func pauseScreenCapture() -> Bool {
        let isok = TRTCCloud.sharedInstance().pauseScreenCapture()==0 ? true:false
        return isok
    }
    
    /// 恢复屏幕分享
    @discardableResult
    func resumeScreenCapture() -> Bool {
        let isok = TRTCCloud.sharedInstance().resumeScreenCapture()==0 ? true:false
        return isok
    }
    
    /// 设置屏幕分享的编码器参数
    func setSubStreamEncoderParam(param:TRTCVideoEncParam) {
        TRTCCloud.sharedInstance().setSubStreamEncoderParam(param)
    }
    
    /// 设置屏幕分享的混音音量大小
    /// - Parameter volume: 设置的音量大小，范围0 - 100
    func setSubStreamMixVolume(volume:Int) {
        TRTCCloud.sharedInstance().setSubStreamMixVolume(volume)
    }
    
    /// 设置屏幕共享参数，该方法在屏幕共享过程中也可以调用
    /// - Parameters:
    ///   - screenSource: 指定分享源
    ///   - rect: 指定捕获的区域（传 CGRectZero 则默认分享全屏）
    ///   - capturesCursor: 是否捕获鼠标光标
    ///   - highlight: 是否高亮正在分享的窗口
    func selectScreenCaptureTarget(screenSource:TRTCScreenCaptureSourceInfo,
                                   rect:CGRect,
                                   capturesCursor:Bool,
                                   highlight:Bool) {
        TRTCCloud.sharedInstance().selectScreenCaptureTarget(screenSource, rect: rect, capturesCursor: capturesCursor, highlight: highlight)
    }
    
    //MARK:- 推流
    /**
     开启推流，必须保证当前流开启
     */
    func startPublishCDNStream(url:String) {
        let parms = TRTCPublishCDNParam()
        parms.appId = Int32(kTencent_push_api_id)!
        parms.bizId = Int32(kTencent_push_bizId)!
        parms.url = url
        TRTCCloud.sharedInstance()?.startPublishCDNStream(parms)
    }
    
    func stopPublishCDNStream() {
        TRTCCloud.sharedInstance()?.stopPublishCDNStream()
    }
    
    func girdForm(ksta:[TkStatistics],roomid:String) -> [TRTCMixUser] {
        var hnum:Int = 1
        var vnum:Int = 1
        switch ksta.count {
        case 1:
            hnum = 1
            vnum = 1
        case 2:
            hnum = 2
            vnum = 1
        case 3:
            hnum = 3
            vnum = 1
        case 4:
            hnum = 2
            vnum = 2
        case 4..<9:
            hnum = 3
            vnum = 3
        case 9...Int.max:
            hnum = 5
            vnum = 5
        default:
            break
        }
        let lwidth = kPushWidth/CGFloat(hnum)
        let lheight = kPushHeight/CGFloat(vnum)
        
        var mixUsers = [TRTCMixUser]()
        var zOrder:Int = 0
        
        //推流必须保证本地流的开启
        let hascurrent = ksta.contains { (tksta) -> Bool in
            let isok = tksta.userId == nil
            if isok {
                if tksta.streamType == .sub {
                    return false
                }
            }
            return isok
        }
        if hascurrent == false {
            if let userid = Td.sh().params.userId {
                let current = TRTCMixUser()
                current.userId = userid
                current.roomID = roomid
                current.zOrder = Int32(zOrder)
                current.streamType = .small
                current.rect = self.actual(maxSize: CGSize.init(width: 1, height: 1), sourceSize: CGSize.init(width: 1, height: 1))
                mixUsers.append(current)
                zOrder+=1
            }
        }
        
        
        for i in 0..<vnum {
            for j in 0..<hnum {
                let indx = i*hnum+j
                if indx > ksta.count-1 {
                    break
                }
                
                let ks = ksta[indx]
                let scale = ks.width/ks.height
                //设置宽高基准的条件
                let scale1 = ks.width/lwidth
                let scale2 = ks.height/lheight
                //根据设备类型去改变高度和y轴
                let width = scale1>scale2 ? lwidth:(lheight*scale)
                let height = scale1>scale2 ? (lwidth/scale):lheight
                let xleft = (lwidth-width)/2
                let ytop = (lheight-height)/2
                let rect = CGRect.init(x: CGFloat(j)*lwidth+xleft, y: CGFloat(i)*lheight+ytop, width: width, height: height)
                
                let mix = TRTCMixUser()
                ///ks.userId==nil ? "$PLACE_HOLDER_LOCAL_MAIN$":"$PLACE_HOLDER_REMOTE$"//
                let userid = ks.userId ?? Td.sh().params.userId!//ks.userId==nil ? "$PLACE_HOLDER_LOCAL_MAIN$":"$PLACE_HOLDER_REMOTE$"// ks.userId ?? Td.sh().params.userId!
                mix.userId = userid
                mix.roomID = roomid
                mix.zOrder = Int32(indx+zOrder)
                mix.streamType = ks.streamType
                mix.pureAudio = false
                mix.rect = rect
                mixUsers.append(mix)
            }
        }
        
        return mixUsers
    }
    
    func actual(maxSize:CGSize,sourceSize:CGSize) -> CGRect {
        let isLanch = (maxSize.width/maxSize.height)>(sourceSize.width/sourceSize.height) ? true:false
        var newWidth:CGFloat = 0,newHeight:CGFloat = 0
        //以宽度/高度为基准
        if isLanch == false {
            newWidth = maxSize.width
            let scale = maxSize.width/sourceSize.width
            newHeight = sourceSize.height*scale
        }else {
            newHeight = maxSize.height
            let scale = maxSize.height/sourceSize.height
            newWidth = sourceSize.width*scale
        }
        
        //中间
        let xleft = (maxSize.width-newWidth)/2
        let ytop = (maxSize.height-newHeight)/2
        return CGRect.init(x: xleft, y: ytop, width: newWidth, height: newHeight)
    }
    
    
    func sharingForm(ksta:[TkStatistics],roomid:String) -> [TRTCMixUser] {
        return self.girdForm(ksta: ksta, roomid: roomid)
    }
    
    
    func form(tks:[TkStatistics],roomid:String) -> [TRTCMixUser] {
        let hasSub = tks.contains(where: {$0.streamType == .sub})
        if hasSub {
            return self.sharingForm(ksta: tks, roomid: roomid)
        }else {
            return self.girdForm(ksta: tks, roomid: roomid)
        }
    }
    
    func setMix(ksta:[TkStatistics],roomid:String) {
        let config = TRTCTranscodingConfig()
        config.mode = TRTCTranscodingConfigMode.manual
        config.appId = Int32(kTencent_push_api_id)!
        config.bizId = Int32(kTencent_push_bizId)!
        config.videoWidth = Int32(kPushWidth)
        config.videoHeight = Int32(kPushHeight)
        config.videoBitrate = 1500//1200
        config.videoFramerate = 20//15
        config.videoGOP = 2
        config.backgroundColor = Int32(0x000000)
        config.audioSampleRate = 48000
        config.audioBitrate = 64
        config.audioChannels = 2
        config.mixUsers = self.form(tks: ksta, roomid: roomid)
        TRTCCloud.sharedInstance()?.setMix(config) //云端混流
        //TRTCCloud.sharedInstance()?.setSubStreamMixVolume(2)
        //TRTCCloud.sharedInstance()?.setSystemVolumeType(TRTCSystemVolumeType.VOIP)
        
    }
    
    class func needPushMix() {
        guard let roomId = Td.sh().params.roomId else {
            return
        }
        if TXLiteManager.shared().isLiving {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
                TXLiteManager.shared().setMix(ksta: TXLiteManager.shared().ksta, roomid: roomId)
            }
        }
    }
    
    class func needAfterPushMix() {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+2) {
            TXLiteManager.needPushMix()
        }
    }
    
    class func reloadCDNStream(rtmpurl:String) {
        if TXLiteManager.shared().isLiving {
            TXLiteManager.shared().startPublishCDNStream(url: rtmpurl)
        }else {
            TXLiteManager.shared().stopPublishCDNStream()
        }
    }
    
    
    deinit {
        //TRTCCloud.sharedInstance()?.exitRoom()
        TRTCCloud.destroySharedIntance()
    }
    
    
}

extension String {
    func isCurretRoom() -> Bool {
       if self == Td.sh().params.roomId {
           return true
       }
       return false
    }
    
    func isCurret() -> Bool {
       if self == Td.sh().params.userId {
           return true
       }
       return false
    }
    
    func isHostId() -> Bool {
        if self == Td.sh().cloud.hostId {
            return true
        }
        return false
    }
    
    func isFocusId() -> Bool {
        if self == Td.sh().cloud.focusId {
            return true
        }
        return false
    }
    
    static func isFocusId() -> Bool {
        return Td.sh().params.userId == Td.sh().cloud.focusId
    }
    
    static func isHostId() -> Bool {
        return Td.sh().params.userId == Td.sh().cloud.hostId
    }
}


//UserInfo 定制版根据userid处理元素
extension Array where Element == UserInfo {
    mutating func lremove(userid:String){
        let indx = self.firstIndex { (info) -> Bool in
            return info.userId==userid
        }
        if let inx = indx {
            self.remove(at: inx)
        }
    }
    mutating func lremoveDuplicates(){
        self = self.lremovingDuplicates()
    }
    
    func lremovingDuplicates() -> [UserInfo] {
        var addedDict = [String: Bool]()
        let news = self.filter { (info) -> Bool in
            return addedDict.updateValue(true, forKey: info.userId!) == nil
        }
        return news
    }
}

//Plist_historyMode 定制版根据userid处理元素
extension Array where Element == Plist_historyMode {
    mutating func hremove(userid:String){
        let indx = self.firstIndex { (info) -> Bool in
            return info.roomId == userid
        }
        if let inx = indx {
            self.remove(at: inx)
        }
    }
    mutating func hremoveDuplicates(){
        self = self.hremovingDuplicates()
    }
    
    func hremovingDuplicates() -> [Plist_historyMode] {
        var addedDict = [String: Bool]()
        let news = self.filter { (info) -> Bool in
            return addedDict.updateValue(true, forKey: info.roomId!) == nil
        }
        return news
    }
}

extension TXLiteManager {
    class func _resolutionFrom(string:String) -> TRTCVideoResolution {
        switch (string) {
            case "160x160":
                return TRTCVideoResolution._160_160;
            case "320x180":
                return TRTCVideoResolution._320_180;
            case "320x240":
                return TRTCVideoResolution._320_240;
            case "480x480":
                return TRTCVideoResolution._480_480;
            case "640x360":
                return TRTCVideoResolution._640_360;
            case "640x480":
                return TRTCVideoResolution._640_480;
            case "960x540":
                return TRTCVideoResolution._960_540;
            case "1280x720":
                return TRTCVideoResolution._1280_720;
            case "1980x1080":
                return TRTCVideoResolution._1920_1080;
            default:
                return TRTCVideoResolution._640_480;
        }
    }
    
    class func _resolutionFromIndex(resolutionIndex:Int) -> TRTCVideoResolution {
        switch (resolutionIndex) {
            case 0:
                return TRTCVideoResolution._160_160;
            case 1:
                return TRTCVideoResolution._320_180;
            case 2:
                return TRTCVideoResolution._320_240;
            case 3:
                return TRTCVideoResolution._480_480;
            case 4:
                return TRTCVideoResolution._640_360;
            case 5:
                return TRTCVideoResolution._640_480;
            case 6:
                return TRTCVideoResolution._960_540;
            case 7:
                return TRTCVideoResolution._1280_720;
            case 8:
                return TRTCVideoResolution._1920_1080;
            default:
                return TRTCVideoResolution._640_480;
        }
    }
    
    class func resolutionString(resolution:TRTCVideoResolution) -> String {
        if (resolution == TRTCVideoResolution._160_160) { return "160x160"}
        if (resolution == TRTCVideoResolution._320_180) { return "320x180"}
        if (resolution == TRTCVideoResolution._320_240) { return "320x240"}
        if (resolution == TRTCVideoResolution._640_360) { return "640x360"}
        if (resolution == TRTCVideoResolution._480_480) { return "480x480"}
        if (resolution == TRTCVideoResolution._640_480) { return "640x480"}
        if (resolution == TRTCVideoResolution._960_540) { return "960x540"}
        if (resolution == TRTCVideoResolution._1280_720) { return "1280x720"}
        if (resolution == TRTCVideoResolution._1920_1080) { return "1920x1080"}
        return "";
    }
}

